Skip to content

passkeys - #32

Merged
JohanHiths merged 17 commits into
mainfrom
passkeys
Apr 21, 2026
Merged

passkeys#32
JohanHiths merged 17 commits into
mainfrom
passkeys

Conversation

@gvaguirres

@gvaguirres gvaguirres commented Apr 18, 2026

Copy link
Copy Markdown
Contributor

Summary by CodeRabbit

  • New Features

    • WebAuthn/passkey authentication added (login and registration flows)
    • New Identity Verification page and client-side WebAuthn utilities
    • "Add Passkeys" UI in profile and admin navigation
    • New /home user landing page
  • Refactor

    • Role-based routing and login success redirects updated (admin vs user)
  • Chores

    • Dev user/admin seed data adjusted; general formatting and cleanup

@coderabbitai

coderabbitai Bot commented Apr 18, 2026

Copy link
Copy Markdown
Contributor

Warning

Rate limit exceeded

@gvaguirres has exceeded the limit for the number of commits that can be reviewed per hour. Please wait 41 minutes and 46 seconds before requesting another review.

Your organization is not enrolled in usage-based pricing. Contact your admin to enable usage-based pricing to continue reviews beyond the rate limit, or try again in 41 minutes and 46 seconds.

⌛ How to resolve this issue?

After the wait time has elapsed, a review can be triggered using the @coderabbitai review command as a PR comment. Alternatively, push new commits to this PR.

We recommend that you space out your commits to avoid hitting the rate limit.

🚦 How do rate limits work?

CodeRabbit enforces hourly rate limits for each developer per organization.

Our paid plans have higher rate limits than the trial, open-source and free plans. In all cases, we re-allow further reviews after a brief timeout.

Please see our FAQ for further information.

ℹ️ Review info
⚙️ Run configuration

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro

Run ID: d8d5904c-02ec-41fa-ad23-00442e04be4b

📥 Commits

Reviewing files that changed from the base of the PR and between 6dcd489 and 88e701a.

📒 Files selected for processing (1)
  • src/main/java/backendlab/team4you/controller/DashboardController.java
📝 Walkthrough

Walkthrough

Added WebAuthn support: new Maven dependency, browser-side WebAuthn JS modules, templates and endpoints for passkey registration/authentication, security config and success handler updates for role-based routing, dev-profile seed accounts, and minor template/import cleanups and newline normalizations.

Changes

Cohort / File(s) Summary
Build & Config
pom.xml, src/main/resources/application.properties
Added com.webauthn4j:webauthn4j-core:0.30.2.RELEASE; normalized trailing newlines.
Startup Data
src/main/java/backendlab/team4you/Team4youApplication.java
Dev-profile now seeds two accounts: devAdmin (ROLE_ADMIN) and devUser (ROLE_USER) with emails and password hashes; added console logs.
Role Model
src/main/java/backendlab/team4you/user/UserRole.java
Renamed enum constants to ROLE_USER and ROLE_ADMIN.
Security Core
src/main/java/backendlab/team4you/config/SecurityConfig.java, src/main/java/backendlab/team4you/config/CustomAuthenticationSuccessHandler.java
Selective CSRF ignores for WebAuthn/files; consolidated/updated authorization matchers for /webauthn/**, /home, /add-passkey; form login processing URL set; UserDetailsService uses authorities; success handler redirects by role and routes credential-present flow to /login/webauthn.
Controllers
src/main/java/backendlab/team4you/controller/SignupController.java, src/main/java/backendlab/team4you/controller/UserController.java, src/main/java/backendlab/team4you/controller/AdminController.java
Replaced /webauthn-check and /dashboard handlers with /login/webauthncheck view; added /home endpoint; removed unused imports in AdminController.
WebAuthn JS Modules
src/main/resources/static/js/abort-controller.js, src/main/resources/static/js/base64url.js, src/main/resources/static/js/http.js, src/main/resources/static/js/webauthn-core.js
Added singleton abort-signal helper, base64url encode/decode, fetch POST helper, and high-level WebAuthn register/authenticate flows (mediation, option decoding, request/response encoding, server validation).
Templates & UI
src/main/resources/templates/check.html, src/main/resources/templates/profile.html, src/main/resources/templates/admin-sidenav.html, src/main/resources/templates/layout.html, src/main/resources/templates/admin-layout.html, src/main/resources/templates/login.html, src/main/resources/templates/home.html, src/main/resources/templates/application.html, src/main/resources/templates/webauthn-check.html
Added check.html (WebAuthn verify) and "Add Passkeys" links; updated asset paths and fragment syntax; removed obsolete webauthn-check.html; normalized newline endings across templates.

Sequence Diagram(s)

sequenceDiagram
    participant Browser as User (Browser)
    participant Server as Spring Server
    participant WebAuthnAPI as WebAuthn API (navigator.credentials)
    participant Auth as Server Authenticator

    Browser->>Server: GET /webauthn/authenticate/options
    Server-->>Browser: JSON auth options (challenge, allowCredentials)
    Browser->>Browser: decode base64url fields
    Browser->>WebAuthnAPI: navigator.credentials.get(options)
    WebAuthnAPI-->>Browser: assertion (authenticatorData, clientDataJSON, signature, userHandle)
    Browser->>Browser: encode assertion fields to base64url
    Browser->>Server: POST /login/webauthn (assertion payload)
    Server->>Auth: validate assertion, verify signature
    alt valid
        Auth-->>Server: authenticated + redirectUrl
        Server-->>Browser: { authenticated:true, redirectUrl }
        Browser->>Browser: redirect to provided URL (/admin or /home)
    else invalid
        Auth-->>Server: failure payload
        Server-->>Browser: { authenticated:false, error }
        Browser->>Browser: display error
    end
Loading

Estimated code review effort

🎯 3 (Moderate) | ⏱️ ~25 minutes

Poem

"A rabbit hopped to seed and key,
I added code for passkeys free,
Challenges dance, base64 twirls,
Signals abort with gentle swirls,
Spring now greets admins and users with glee."

🚥 Pre-merge checks | ✅ 1 | ❌ 2

❌ Failed checks (1 warning, 1 inconclusive)

Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 5.56% which is insufficient. The required threshold is 80.00%. Write docstrings for the functions missing them to satisfy the coverage threshold.
Title check ❓ Inconclusive The title 'passkeys' is vague and generic, lacking specificity about the changes made. While it relates to one aspect of the PR, it does not clearly convey the primary changes such as WebAuthn integration, security configuration updates, or role-based routing. Consider revising the title to be more descriptive, such as 'Integrate WebAuthn passkeys authentication with role-based routing' or 'Add WebAuthn support and update security configuration for role-based access control'.
✅ Passed checks (1 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.

✏️ Tip: You can configure your own custom pre-merge checks in the settings.

✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch passkeys

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands and usage tips.

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 12

Caution

Some comments are outside the diff and can’t be posted inline due to platform limitations.

⚠️ Outside diff range comments (1)
src/main/java/backendlab/team4you/controller/SignupController.java (1)

60-61: ⚠️ Potential issue | 🟠 Major

Remove the "ROLE_" prefix since UserEntity.getRole() already returns the prefixed enum name.

UserRole enum values are ROLE_USER and ROLE_ADMIN. The getRole() method calls .name() on the enum, returning strings like "ROLE_USER". Concatenating "ROLE_" + creates "ROLE_ROLE_USER", which breaks Spring Security role checks—newly signed-up users cannot be authorized with hasRole("USER") or hasAnyRole("USER", "ADMIN").

Proposed fix
         Authentication auth = new UsernamePasswordAuthenticationToken(
-                userEntity.getName(), null, List.of(new SimpleGrantedAuthority("ROLE_" + userEntity.getRole())));
+                userEntity.getName(), null, List.of(new SimpleGrantedAuthority(userEntity.getRole())));
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@src/main/java/backendlab/team4you/controller/SignupController.java` around
lines 60 - 61, The Authentication creation in SignupController is adding an
extra "ROLE_" prefix to roles, causing values like "ROLE_ROLE_USER"; remove the
manual prefix so the authority uses the exact role string returned by
userEntity.getRole() when constructing the SimpleGrantedAuthority for the
UsernamePasswordAuthenticationToken (update the Authentication auth = new
UsernamePasswordAuthenticationToken(...) call to pass List.of(new
SimpleGrantedAuthority(userEntity.getRole())) instead of "ROLE_" +
userEntity.getRole()).
🧹 Nitpick comments (4)
pom.xml (1)

141-146: Remove this explicit dependency unless there is a specific reason for pinning to 0.30.2.RELEASE.

spring-security-webauthn (7.0.4) transitively brings webauthn4j-core at version 0.31.x, which is newer than the pinned 0.30.2.RELEASE. While 0.30.2.RELEASE is compatible with no reported breaking changes, pinning to an older version needs justification. If no direct WebAuthn4J APIs are used by application code, remove this dependency and rely on the transitive version from Spring Security WebAuthn.

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@pom.xml` around lines 141 - 146, The pom declares an explicit dependency
com.webauthn4j:webauthn4j-core:0.30.2.RELEASE which downgrades the transitive
version brought in by spring-security-webauthn (7.0.4); remove this explicit
dependency from the POM unless application code directly uses WebAuthn4J APIs,
or if you must keep it, update the version to match the transitive 0.31.x and
add a short comment justifying the pin. Locate the dependency block for
com.webauthn4j:webauthn4j-core in the POM, delete it (or change its <version> to
the transitive version and add justification), then run mvn dependency:tree to
confirm the intended version is used.
src/main/resources/static/js/webauthn-core.js (2)

100-100: Remove stray dead comment inside the try block.

Line 100 has a leftover commented-out conditional that no longer matches the logic below. Either delete it or move the note outside the try.

🧹 Proposed cleanup
         authenticationResponse = await authenticationCallResponse.json();
-        //   if (authenticationResponse && authenticationResponse.authenticated) {
     } catch (err) {
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@src/main/resources/static/js/webauthn-core.js` at line 100, There is a stray
commented-out conditional "//   if (authenticationResponse &&
authenticationResponse.authenticated) {" left inside the try block in
webauthn-core.js; remove this dead comment (or, if you need to keep a note, move
it outside the try block as a regular comment) so the try block only contains
active logic and relevant comments referencing authenticationResponse.

43-43: Replace manual base64url decoding with native PublicKeyCredential JSON parsing and add response type validation.

The three FIXME markers flag standards-compliant improvements:

  1. Lines 43 & 132: Replace manual base64url decoding of allowCredentials / excludeCredentials and challenge with PublicKeyCredential.parseRequestOptionsFromJSON() and PublicKeyCredential.parseCreationOptionsFromJSON(). These native APIs are now widely supported (Chrome 129+, Firefox 119+, Safari 18.4+, per WebAuthn Level 3).

  2. Line 160: Add validation that response instanceof AuthenticatorAttestationResponse before accessing response.attestationObject. This prevents confusing failures if a user mistakenly selects an assertion credential instead of an attestation response.

While the current manual approach is functionally equivalent, addressing these will align with W3C standards and improve error clarity.

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@src/main/resources/static/js/webauthn-core.js` at line 43, Replace the manual
base64url decoding logic for challenge and credential descriptors by calling the
native parsers: use PublicKeyCredential.parseRequestOptionsFromJSON() where you
currently decode allowCredentials/excludeCredentials and challenge (refer to the
variables allowCredentials, excludeCredentials, challenge and the code paths
handling navigator.credentials.get) and use
PublicKeyCredential.parseCreationOptionsFromJSON() where you decode creation
options for registration (refer to the registration/creation code path and any
createCredentials handling); additionally, before accessing
response.attestationObject in the registration flow, validate that response
instanceof AuthenticatorAttestationResponse and handle the error case if it is
not to avoid wrong-response type crashes. Ensure you replace the manual
base64url-to-ArrayBuffer conversions with the parse*FromJSON calls and add the
instanceof check and clear error handling around response.attestationObject
access.
src/main/java/backendlab/team4you/config/CustomAuthenticationSuccessHandler.java (1)

47-56: Role check is fine; consider using AuthorityUtils for clarity.

Functionally correct. A small readability improvement using Spring's helper:

♻️ Optional refactor
-        var authorities = authentication.getAuthorities();
-
-        boolean isAdmin = authorities.stream()
-                .anyMatch(a -> a.getAuthority().equals("ROLE_ADMIN"));
-
-        if (isAdmin)
-            getRedirectStrategy().sendRedirect(request, response, "/admin");
-        else {
-            getRedirectStrategy().sendRedirect(request, response, "/home");
-        }
+        boolean isAdmin = AuthorityUtils.authorityListToSet(authentication.getAuthorities())
+                .contains("ROLE_ADMIN");
+        String target = isAdmin ? "/admin" : "/home";
+        getRedirectStrategy().sendRedirect(request, response, target);

Note: /home requires hasRole("USER") in SecurityConfig, so any authenticated principal without ROLE_USER or ROLE_ADMIN that reaches this branch will get a 403 on the redirect target. That's only a concern if you introduce other roles later.

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In
`@src/main/java/backendlab/team4you/config/CustomAuthenticationSuccessHandler.java`
around lines 47 - 56, Replace the manual stream-based role check with Spring's
AuthorityUtils for clarity: import
org.springframework.security.core.authority.AuthorityUtils and compute isAdmin
by converting the authentication authorities to a Set via
AuthorityUtils.authorityListToSet(authentication.getAuthorities()) and checking
contains("ROLE_ADMIN"); keep the existing
getRedirectStrategy().sendRedirect(request, response, "/admin") and the else
branch to "/home" unchanged (ensure this method is used inside
onAuthenticationSuccess in CustomAuthenticationSuccessHandler).
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Inline comments:
In
`@src/main/java/backendlab/team4you/config/CustomAuthenticationSuccessHandler.java`:
- Around line 36-45: Remove the dead isWebAuthn check in
CustomAuthenticationSuccessHandler: the Authentication passed to the
formLogin().successHandler(...) will never be a
WebAuthnAuthenticationRequestToken, so delete the boolean isWebAuthn variable
and the conditional that uses it and simplify the flow that checks userEntity
and credentials; if you actually need to prevent redirect loops for
WebAuthn-authenticated users instead either wire this handler into the
webAuthn(...) configurer (instead of only formLogin().successHandler(...)) or
implement the loop-prevention logic in the WebAuthn success handler rather than
keeping the unreachable isWebAuthn check.

In `@src/main/java/backendlab/team4you/config/SecurityConfig.java`:
- Line 28: The CSRF ignore list in SecurityConfig erroneously disables CSRF for
the form-login endpoint; remove "/login" from the csrf.ignoringRequestMatchers
call so the line only ignores the WebAuthn and files endpoints (e.g., keep
"/webauthn/**" and "/api/files/**" but not "/login"), and if the app’s login
form is missing a CSRF token ensure the login page template injects the _csrf
hidden input (or uses Spring's form tag) so POST /login includes the token.
- Around line 78-83: The signup flow is creating a double-prefixed role string;
in SignupController where authentication is constructed using "ROLE_" +
userEntity.getRole(), remove the extra "ROLE_" prefix and use
userEntity.getRole() directly so it matches SecurityConfig's
User.builder().authorities(user.getRole()) and the seeded roles (e.g.,
ROLE_USER/ROLE_ADMIN); update the authentication creation to pass the existing
role string and ensure any related checks expect the single-prefixed format.
- Around line 33-41: SecurityConfig has inconsistent requestMatcher paths and
role checks: align the "/login/webauthn" matcher with the SignupController
mapping and success handler by permitting "/login/webauthn/" (include the
trailing slash) or add both "/login/webauthn" and "/login/webauthn/"; change the
"/home" matcher from hasRole("USER") to hasAnyRole("USER","ADMIN") if admins
should access /home (adjust in SecurityConfig where
requestMatchers("/home").hasRole("USER") is declared) ; and remove the unused
permitAll matcher for "/webauthn/login/**" (or replace it with the correct
WebAuthn endpoints like "/webauthn/authenticate/**" if needed) so
SecurityConfig, SignupController, and CustomAuthenticationSuccessHandler paths
are consistent.

In `@src/main/java/backendlab/team4you/controller/SignupController.java`:
- Around line 37-39: The controller mapping in SignupController.webauthnCheck
currently only uses "/login/webauthn/" which mismatches SecurityConfig and other
code that use "/login/webauthn"; update the mapping to consistently accept both
variants (e.g. replace `@GetMapping`("/login/webauthn/") with
`@GetMapping`({"/login/webauthn", "/login/webauthn/"}) on webauthnCheck), and
normalize any redirects in CustomAuthenticationSuccessHandler and client-side
HTML/JS to use the same canonical path (preferably "/login/webauthn") so
SecurityConfig rules apply consistently.

In `@src/main/java/backendlab/team4you/Team4youApplication.java`:
- Around line 24-50: The seeding currently runs only when repository.count() ==
0 so existing DBs won't get the new admin; change Team4youApplication to check
and create each account idempotently by calling repository.findByName("dev") and
repository.findByName("user") (or equivalent find method) and only
constructing/saving the corresponding UserEntity (devAdmin / devUser) when the
find returns empty; reuse encoder.encode(...) and repository.save(...) as in the
diff, and keep role/email/password setup identical but guarded per-account
instead of a single repository.count() gate.

In `@src/main/java/backendlab/team4you/user/UserRole.java`:
- Around line 5-6: Add a Flyway SQL migration that backfills old enum names to
the new ones before deploying the enum rename: create a new migration (e.g.,
Vx__backfill_user_roles.sql) containing the two updates "UPDATE user_entities
SET role = 'ROLE_USER' WHERE role = 'USER';" and "UPDATE user_entities SET role
= 'ROLE_ADMIN' WHERE role = 'ADMIN';" and ensure it runs prior to the code
deploy; also review UserRole and UserEntity.setRole(String role) to ensure they
rely on the migrated values (or add a temporary tolerant mapping from
'USER'/'ADMIN' to 'ROLE_USER'/'ROLE_ADMIN' inside setRole to avoid valueOf()
failures until the migration is applied).

In `@src/main/resources/static/js/base64url.js`:
- Around line 20-22: The encode function uses String.fromCharCode(...new
Uint8Array(buffer)) which can hit argument count limits for large buffers;
replace the spread usage with a chunked conversion: create a Uint8Array bytes =
new Uint8Array(buffer), iterate in slices (e.g. step = 0x8000), build a string
by concatenating String.fromCharCode.apply(null, bytes.subarray(i, i+step)) or
using String.fromCharCode(...slice) per chunk, then call window.btoa on the
assembled string and keep the existing replace chain to produce base64url;
update the encode function (and the local base64 variable/window.btoa call) to
use this chunking approach.

In `@src/main/resources/templates/check.html`:
- Around line 50-57: The code discards the server-provided post-auth redirect by
hardcoding window.location.href = "/", so change the await call to capture the
resolved value from webauthn.authenticate (e.g., const authenticationResponse =
await webauthn.authenticate(...)) and then set window.location.href to
authenticationResponse.redirectUrl when present, falling back to "/" only if
redirectUrl is missing; keep the existing catch block unchanged for error
handling.

In `@src/main/resources/templates/fragments/admin-sidenav.html`:
- Line 40: The anchor element using a hardcoded href (the <a ...
href="/webauthn/register" ...> in the admin-sidenav fragment) should be changed
to use Thymeleaf URL generation: replace the static href attribute with a
th:href that generates the URL with the application's context path (e.g.
th:href="@{/webauthn/register}") so navigation works correctly under different
context-path deployments and consistent with other links in this fragment.

In `@src/main/resources/templates/login.html`:
- Line 17: fragments/form-errors.html currently defines th:fragment="errors"
twice which causes unpredictable resolution in login.html; edit
fragments/form-errors.html to remove the duplicate and consolidate into a single
th:fragment="errors" that renders the same markup for both cases by checking
both ${param.error} and ${error} (e.g., use a combined conditional that prefers
${param.error} but falls back to ${error} and displays the message), leaving
login.html's th:replace="~{fragments/form-errors :: errors}" unchanged so it
resolves deterministically.

In `@src/main/resources/templates/profile.html`:
- Line 25: The anchor uses a hard-coded href (href="/webauthn/register") which
ignores the app context path; replace it with Thymeleaf URL rewriting by
changing the attribute to th:href with a context-aware expression (e.g.,
@{/webauthn/register}) on the same anchor element so the passkey link resolves
correctly when the app is deployed under a context path; keep existing
class/style attributes and remove or replace the static href attribute on the
<a> element in profile.html.

---

Outside diff comments:
In `@src/main/java/backendlab/team4you/controller/SignupController.java`:
- Around line 60-61: The Authentication creation in SignupController is adding
an extra "ROLE_" prefix to roles, causing values like "ROLE_ROLE_USER"; remove
the manual prefix so the authority uses the exact role string returned by
userEntity.getRole() when constructing the SimpleGrantedAuthority for the
UsernamePasswordAuthenticationToken (update the Authentication auth = new
UsernamePasswordAuthenticationToken(...) call to pass List.of(new
SimpleGrantedAuthority(userEntity.getRole())) instead of "ROLE_" +
userEntity.getRole()).

---

Nitpick comments:
In `@pom.xml`:
- Around line 141-146: The pom declares an explicit dependency
com.webauthn4j:webauthn4j-core:0.30.2.RELEASE which downgrades the transitive
version brought in by spring-security-webauthn (7.0.4); remove this explicit
dependency from the POM unless application code directly uses WebAuthn4J APIs,
or if you must keep it, update the version to match the transitive 0.31.x and
add a short comment justifying the pin. Locate the dependency block for
com.webauthn4j:webauthn4j-core in the POM, delete it (or change its <version> to
the transitive version and add justification), then run mvn dependency:tree to
confirm the intended version is used.

In
`@src/main/java/backendlab/team4you/config/CustomAuthenticationSuccessHandler.java`:
- Around line 47-56: Replace the manual stream-based role check with Spring's
AuthorityUtils for clarity: import
org.springframework.security.core.authority.AuthorityUtils and compute isAdmin
by converting the authentication authorities to a Set via
AuthorityUtils.authorityListToSet(authentication.getAuthorities()) and checking
contains("ROLE_ADMIN"); keep the existing
getRedirectStrategy().sendRedirect(request, response, "/admin") and the else
branch to "/home" unchanged (ensure this method is used inside
onAuthenticationSuccess in CustomAuthenticationSuccessHandler).

In `@src/main/resources/static/js/webauthn-core.js`:
- Line 100: There is a stray commented-out conditional "//   if
(authenticationResponse && authenticationResponse.authenticated) {" left inside
the try block in webauthn-core.js; remove this dead comment (or, if you need to
keep a note, move it outside the try block as a regular comment) so the try
block only contains active logic and relevant comments referencing
authenticationResponse.
- Line 43: Replace the manual base64url decoding logic for challenge and
credential descriptors by calling the native parsers: use
PublicKeyCredential.parseRequestOptionsFromJSON() where you currently decode
allowCredentials/excludeCredentials and challenge (refer to the variables
allowCredentials, excludeCredentials, challenge and the code paths handling
navigator.credentials.get) and use
PublicKeyCredential.parseCreationOptionsFromJSON() where you decode creation
options for registration (refer to the registration/creation code path and any
createCredentials handling); additionally, before accessing
response.attestationObject in the registration flow, validate that response
instanceof AuthenticatorAttestationResponse and handle the error case if it is
not to avoid wrong-response type crashes. Ensure you replace the manual
base64url-to-ArrayBuffer conversions with the parse*FromJSON calls and add the
instanceof check and clear error handling around response.attestationObject
access.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro

Run ID: f9d8b803-6881-4915-9cd0-2c7703d7ebef

📥 Commits

Reviewing files that changed from the base of the PR and between 86cfbc5 and 5a723c3.

📒 Files selected for processing (23)
  • pom.xml
  • src/main/java/backendlab/team4you/Team4youApplication.java
  • src/main/java/backendlab/team4you/config/CustomAuthenticationSuccessHandler.java
  • src/main/java/backendlab/team4you/config/SecurityConfig.java
  • src/main/java/backendlab/team4you/controller/AdminController.java
  • src/main/java/backendlab/team4you/controller/SignupController.java
  • src/main/java/backendlab/team4you/controller/UserController.java
  • src/main/java/backendlab/team4you/user/UserRole.java
  • src/main/resources/application.properties
  • src/main/resources/static/components/form.css
  • src/main/resources/static/js/abort-controller.js
  • src/main/resources/static/js/base64url.js
  • src/main/resources/static/js/http.js
  • src/main/resources/static/js/webauthn-core.js
  • src/main/resources/templates/admin-layout.html
  • src/main/resources/templates/application.html
  • src/main/resources/templates/check.html
  • src/main/resources/templates/fragments/admin-sidenav.html
  • src/main/resources/templates/home.html
  • src/main/resources/templates/layout.html
  • src/main/resources/templates/login.html
  • src/main/resources/templates/profile.html
  • src/main/resources/templates/webauthn-check.html
💤 Files with no reviewable changes (2)
  • src/main/java/backendlab/team4you/controller/AdminController.java
  • src/main/resources/templates/webauthn-check.html

Comment thread src/main/java/backendlab/team4you/config/CustomAuthenticationSuccessHandler.java Outdated
Comment thread src/main/java/backendlab/team4you/config/SecurityConfig.java Outdated
Comment on lines 33 to +41
.requestMatchers( "/","/login", "/login/webauthn", "/signup", "/error").permitAll()
.requestMatchers("/webauthn/authenticate/**").permitAll()
.requestMatchers("/api/files/**").permitAll()

.requestMatchers("/api/files/**", "/webauthn/authenticate/**", "/webauthn/login/**").permitAll()

// .requestMatchers("/profile", "/logout").authenticated()
.requestMatchers("/webauthn-check").authenticated()
.requestMatchers("/webauthn/**").hasAnyRole("USER", "ADMIN")

.requestMatchers("/admin/**").hasRole("ADMIN")
.requestMatchers("/dashboard", "/profile/**").hasAnyRole("USER", "ADMIN")
.requestMatchers("/add-passkey").hasAnyRole("USER", "ADMIN")
.requestMatchers("/webauthn/register/**").hasAnyRole("USER", "ADMIN")
.requestMatchers("/home", "/profile/**").hasRole("USER")
.requestMatchers("/add-passkey", "/webauthn/register/**").hasAnyRole("USER", "ADMIN")

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🟡 Minor

🧩 Analysis chain

🏁 Script executed:

#!/bin/bash
# Check controller mappings vs. security matchers for the /login/webauthn paths
rg -nP --type=java -C2 '"/login/webauthn/?"'
rg -nP --type=java -C2 '"/webauthn/login'

Repository: ithsjava25/project-backend-team4you

Length of output: 2502


🏁 Script executed:

#!/bin/bash
# 1. Check for /home endpoint mappings
echo "=== Searching for /home endpoint mapping ==="
rg -nP --type=java '"/home' src/

# 2. Check for /webauthn/login endpoint (not the matcher, but actual endpoints)
echo "=== Searching for /webauthn/login endpoint ==="
rg -nP --type=java '@GetMapping|@PostMapping|@RequestMapping' src/ | grep -i webauthn

# 3. Check CustomAuthenticationSuccessHandler to see admin routing
echo "=== Examining CustomAuthenticationSuccessHandler ==="
rg -nP --type=java -A 10 'isAdmin|ADMIN' src/main/java/backendlab/team4you/config/CustomAuthenticationSuccessHandler.java

Repository: ithsjava25/project-backend-team4you

Length of output: 1091


🏁 Script executed:

#!/bin/bash
# Search for WebAuthn configuration
echo "=== Searching for WebAuthn configuration ==="
fd -t f '\.java$' src/ | xargs grep -l -i 'webauthn' | head -20

echo "=== Check what WebAuthn library is being used ==="
grep -i webauthn pom.xml build.gradle 2>/dev/null || echo "Checking for pom.xml/build.gradle..."

# Search for WebAuthn endpoints more broadly
echo "=== All webauthn-related endpoint mappings ==="
rg -nP --type=java '@(Get|Post|Put|Delete)Mapping.*webauthn' -i

# Check for WebAuthnConfigurer or similar Spring Security WebAuthn configuration
echo "=== WebAuthnConfigurer or security configuration for webauthn ==="
rg -nP --type=java 'WebAuthConfigurer|webauthnConfigurer|/webauthn' src/main/java/backendlab/team4you/config/

Repository: ithsjava25/project-backend-team4you

Length of output: 2360


🏁 Script executed:

#!/bin/bash
# Read the full SecurityConfig.java file
echo "=== Full SecurityConfig.java ==="
cat -n src/main/java/backendlab/team4you/config/SecurityConfig.java

Repository: ithsjava25/project-backend-team4you

Length of output: 4893


Path matcher inconsistencies worth tightening.

A few issues in the authorize chain:

  1. /login/webauthn vs /login/webauthn/SignupController maps @GetMapping("/login/webauthn/") (trailing slash), but the matcher on line 33 is /login/webauthn without a trailing slash. With MVC useTrailingSlashMatch disabled by default since Spring 6, the two are distinct paths. CustomAuthenticationSuccessHandler redirects to /login/webauthn/ (with slash), confirming the mismatch. This creates a subtle inconsistency:

    -.requestMatchers( "/","/login", "/login/webauthn", "/signup", "/error").permitAll()
    +.requestMatchers("/", "/login", "/login/webauthn/", "/signup", "/error").permitAll()
  2. /home requires hasRole("USER") — Users with only ROLE_ADMIN are denied at /home. While CustomAuthenticationSuccessHandler routes admins to /admin so this doesn't affect normal flow, the config is semantically inconsistent. Any future link to /home from an admin session would still 403. Consider hasAnyRole("USER","ADMIN") unless that exclusion is intentional.

  3. /webauthn/login/** permitAll — No controller endpoint for /webauthn/login exists. Spring Security's WebAuthn library provides /webauthn/authenticate and /webauthn/register endpoints, but not /webauthn/login/**. This matcher appears to be dead configuration; remove it if unneeded.

📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
.requestMatchers( "/","/login", "/login/webauthn", "/signup", "/error").permitAll()
.requestMatchers("/webauthn/authenticate/**").permitAll()
.requestMatchers("/api/files/**").permitAll()
.requestMatchers("/api/files/**", "/webauthn/authenticate/**", "/webauthn/login/**").permitAll()
// .requestMatchers("/profile", "/logout").authenticated()
.requestMatchers("/webauthn-check").authenticated()
.requestMatchers("/webauthn/**").hasAnyRole("USER", "ADMIN")
.requestMatchers("/admin/**").hasRole("ADMIN")
.requestMatchers("/dashboard", "/profile/**").hasAnyRole("USER", "ADMIN")
.requestMatchers("/add-passkey").hasAnyRole("USER", "ADMIN")
.requestMatchers("/webauthn/register/**").hasAnyRole("USER", "ADMIN")
.requestMatchers("/home", "/profile/**").hasRole("USER")
.requestMatchers("/add-passkey", "/webauthn/register/**").hasAnyRole("USER", "ADMIN")
.requestMatchers("/", "/login", "/login/webauthn/", "/signup", "/error").permitAll()
.requestMatchers("/api/files/**", "/webauthn/authenticate/**", "/webauthn/login/**").permitAll()
.requestMatchers("/webauthn/**").hasAnyRole("USER", "ADMIN")
.requestMatchers("/admin/**").hasRole("ADMIN")
.requestMatchers("/home", "/profile/**").hasRole("USER")
.requestMatchers("/add-passkey", "/webauthn/register/**").hasAnyRole("USER", "ADMIN")
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@src/main/java/backendlab/team4you/config/SecurityConfig.java` around lines 33
- 41, SecurityConfig has inconsistent requestMatcher paths and role checks:
align the "/login/webauthn" matcher with the SignupController mapping and
success handler by permitting "/login/webauthn/" (include the trailing slash) or
add both "/login/webauthn" and "/login/webauthn/"; change the "/home" matcher
from hasRole("USER") to hasAnyRole("USER","ADMIN") if admins should access /home
(adjust in SecurityConfig where requestMatchers("/home").hasRole("USER") is
declared) ; and remove the unused permitAll matcher for "/webauthn/login/**" (or
replace it with the correct WebAuthn endpoints like "/webauthn/authenticate/**"
if needed) so SecurityConfig, SignupController, and
CustomAuthenticationSuccessHandler paths are consistent.

Comment on lines 78 to 83
return User.builder()
.username(user.getName())
.password(user.getPasswordHash())
.roles(user.getRole())
.authorities(user.getRole())
.accountLocked(false)
.build();

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🔴 Critical

🧩 Analysis chain

🏁 Script executed:

#!/bin/bash
# Inspect the role enum and any string concatenation around roles in the codebase.
rg -nP --type=java -C2 '\bUserRole\.'
rg -nP --type=java -C2 '"ROLE_'
ast-grep --pattern 'enum UserRole { $$$ }'

Repository: ithsjava25/project-backend-team4you

Length of output: 2540


🏁 Script executed:

# Find and inspect the UserRole enum definition
fd -t f UserRole.java

Repository: ithsjava25/project-backend-team4you

Length of output: 131


🏁 Script executed:

# Read the UserEntity.getRole() method to see its return type
rg -n "getRole" src/main/java/backendlab/team4you/user/UserEntity.java -A 3

Repository: ithsjava25/project-backend-team4you

Length of output: 159


🏁 Script executed:

# Search for the UserRole enum definition with ast-grep and also cat the file if found
find . -name "UserRole.java" -type f

Repository: ithsjava25/project-backend-team4you

Length of output: 133


🏁 Script executed:

# Read the full UserRole enum definition
cat -n src/main/java/backendlab/team4you/user/UserRole.java

Repository: ithsjava25/project-backend-team4you

Length of output: 227


Fix double-prefix bug in SignupController authentication setup.

The concern is partially addressed: UserEntity.getRole() does return ROLE_-prefixed strings because the UserRole enum constants are named ROLE_USER and ROLE_ADMIN. The SecurityConfig change from .roles(...) to .authorities(user.getRole()) is therefore safe and correct.

However, verification reveals a critical bug in SignupController.java:61 where the authentication is created with a double-prefixed role:

"ROLE_" + userEntity.getRole()  // produces "ROLE_ROLE_USER" or "ROLE_ROLE_ADMIN"

This must be corrected to just userEntity.getRole() to match the role format used elsewhere (Team4youApplication seeding and now SecurityConfig). The mismatched role prefix will cause authentication and authorization checks to fail silently for signup users.

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@src/main/java/backendlab/team4you/config/SecurityConfig.java` around lines 78
- 83, The signup flow is creating a double-prefixed role string; in
SignupController where authentication is constructed using "ROLE_" +
userEntity.getRole(), remove the extra "ROLE_" prefix and use
userEntity.getRole() directly so it matches SecurityConfig's
User.builder().authorities(user.getRole()) and the seeded roles (e.g.,
ROLE_USER/ROLE_ADMIN); update the authentication creation to pass the existing
role string and ensure any related checks expect the single-prefixed format.

Comment on lines +37 to +39
@GetMapping("/login/webauthn/")
public String webauthnCheck() {
return "check";

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🟡 Minor

🧩 Analysis chain

🏁 Script executed:

#!/bin/bash
# Check whether login WebAuthn paths are defined consistently.
rg -n -C2 'login/webauthn/?' src/main/java src/main/resources

Repository: ithsjava25/project-backend-team4you

Length of output: 2767


Normalize the WebAuthn login route with SecurityConfig.

The mapping uses /login/webauthn/ with a trailing slash, while SecurityConfig.java permits /login/webauthn without one. Additionally, CustomAuthenticationSuccessHandler.java redirects to /login/webauthn/, but the HTML form and JavaScript requests target /login/webauthn. This inconsistency creates unnecessary path variability. Support both variants to ensure consistent security rule application.

Proposed fix
-    `@GetMapping`("/login/webauthn/")
+    `@GetMapping`({"/login/webauthn", "/login/webauthn/"})
     public String webauthnCheck() {
         return "check";
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
@GetMapping("/login/webauthn/")
public String webauthnCheck() {
return "check";
`@GetMapping`({"/login/webauthn", "/login/webauthn/"})
public String webauthnCheck() {
return "check";
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@src/main/java/backendlab/team4you/controller/SignupController.java` around
lines 37 - 39, The controller mapping in SignupController.webauthnCheck
currently only uses "/login/webauthn/" which mismatches SecurityConfig and other
code that use "/login/webauthn"; update the mapping to consistently accept both
variants (e.g. replace `@GetMapping`("/login/webauthn/") with
`@GetMapping`({"/login/webauthn", "/login/webauthn/"}) on webauthnCheck), and
normalize any redirects in CustomAuthenticationSuccessHandler and client-side
HTML/JS to use the same canonical path (preferably "/login/webauthn") so
SecurityConfig rules apply consistently.

Comment on lines +20 to +22
encode: function (buffer) {
const base64 = window.btoa(String.fromCharCode(...new Uint8Array(buffer)));
return base64.replace(/=/g, "").replace(/\+/g, "-").replace(/\//g, "_");

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🟡 Minor

🧩 Analysis chain

🏁 Script executed:

git ls-files | grep -i base64

Repository: ithsjava25/project-backend-team4you

Length of output: 120


🏁 Script executed:

find . -name "base64url.js" -o -name "*base64*"

Repository: ithsjava25/project-backend-team4you

Length of output: 122


🏁 Script executed:

cat -n src/main/resources/static/js/base64url.js

Repository: ithsjava25/project-backend-team4you

Length of output: 1513


🌐 Web query:

String.fromCharCode argument limit JavaScript browser maximum arguments

💡 Result:

There is no specified maximum number of arguments for String.fromCharCode in the ECMAScript standard or official documentation like MDN. The method accepts a variable number of numeric arguments (num1, ..., numN), each representing a UTF-16 code unit between 0 and 65535.

Citations:


🌐 Web query:

WebAuthn attestation credential data maximum size bytes

💡 Result:

There is no defined maximum size in the WebAuthn specification for attestation credential data. The WebAuthn Level 3 specification (as of 2026) does not specify a maximum size for the attestationObject, which contains the authenticatorData (including attestedCredentialData with credentialPublicKey) and attStmt. The credential ID within attestedCredentialData is limited to at most 1023 bytes. The credentialPublicKey is a variable-length COSE_Key whose length must be parsed from CBOR, with no explicit maximum. CTAP specifications require authenticators to support messages of at least 1024 bytes by default (via maxMsgSize), but responses like authenticatorMakeCredential can be larger depending on transport (e.g., up to ~7600 bytes for USB HID). A recent proposal suggests non-normative guidance of attestationObject <= 8 KB, but this is not official. In practice, sizes are typically a few hundred to a few thousand bytes, limited by transport and authenticator capabilities.

Citations:


🌐 Web query:

JavaScript engine String.fromCharCode stack overflow maximum arguments V8 SpiderMonkey

💡 Result:

JavaScript engines impose practical limits on the maximum number of arguments that can be passed to String.fromCharCode, particularly when using spread syntax (...) or Function.prototype.apply. These limits arise from implementation constraints like stack size, FixedArray capacity in V8, and resource allocation policies, not from the ECMAScript specification, which allows arbitrary-length argument lists. For V8 (Chrome, Node.js): - Spread syntax or apply typically fails around 125,000-130,000 arguments with "RangeError: too many function arguments" or "Maximum call stack size exceeded". - Tied to FixedArray::kMaxLength, approximately 64MB or 128MB worth of elements (around 8-16 million in some configs, but practical stack limits reduce it to ~125k). - Older tests showed ~65k-131k depending on version and call method. For SpiderMonkey (Firefox): - Higher tolerance, up to ~500,000 arguments via apply in older tests (Firefox 30/106). - May throw stack overflow for very large lists but generally handles more than V8. Workarounds for large inputs (e.g., Uint8Array to string): - Chunk the array and concatenate results: process in batches of ~65k or less. - Use TextDecoder: new TextDecoder.decode(uint8Array) - efficient, no argument limit issues. - Avoid spread/apply for large arrays; loop or reduce instead. No official documentation specifies exact current (2026) limits as they are internal and version-dependent. Test in target environment or use chunking/TextDecoder for safety. MDN notes no validity checks on inputs but omits argument count limits.

Citations:


🌐 Web query:

String.fromCharCode too many arguments error RangeError JavaScript

💡 Result:

The RangeError "too many arguments" with String.fromCharCode occurs when passing too many arguments to the function, typically via the spread operator (...) on large arrays (e.g., Uint8Array from file buffers > ~500KB) or Function.prototype.apply with large arrays. JavaScript engines impose implementation-specific limits on the number of arguments a function call can accept, often around 65K-500K depending on the browser and stack state (e.g., Chrome ~65K literal, higher with apply; Firefox ~65K literal, 500K apply). The ECMAScript spec does not define a hard limit, but practical constraints exist due to stack size and memory. This error is common when converting binary data (ArrayBuffer, Uint8Array) to strings for base64 encoding, like btoa(String.fromCharCode(...new Uint8Array(buffer))), which fails for files larger than a few hundred KB. To fix, process the array in smaller chunks to stay under the argument limit: function uint8ArrayToStringChunked(uint8Array, chunkSize = 32768) { let result = ''; for (let i = 0; i < uint8Array.length; i += chunkSize) { const chunk = uint8Array.subarray(i, i + chunkSize); result += String.fromCharCode.apply(null, chunk); } return result; } // Usage for base64: function bufferToBase64(buffer) { return btoa(uint8ArrayToStringChunked(new Uint8Array(buffer))); } Using subarray and apply(null, chunk) is efficient and avoids quadratic string concatenation. Chunk sizes like 32K-65K work across browsers; test for your environment. Alternatives include TextEncoder/Decoder for UTF-8 (if data is text) or modern TypedArray methods, but for latin1/binary-to-string, this is standard. MDN docs confirm String.fromCharCode accepts a variable number of UTF-16 code units (0-65535) with no explicit limit mentioned.

Citations:


Use chunking to avoid potential argument limit issues with spread operator.

While String.fromCharCode(...bytes) works fine for typical WebAuthn attestation buffers (usually a few KB), JavaScript engines impose practical argument limits on spread operator calls—around 125K in Chrome and higher in Firefox. Chunking the buffer is a defensive best practice that ensures compatibility regardless of buffer size.

Proposed fix
     encode: function (buffer) {
-        const base64 = window.btoa(String.fromCharCode(...new Uint8Array(buffer)));
+        const bytes = new Uint8Array(buffer);
+        let binary = "";
+        const chunkSize = 0x8000;
+        for (let i = 0; i < bytes.length; i += chunkSize) {
+            binary += String.fromCharCode(...bytes.subarray(i, i + chunkSize));
+        }
+        const base64 = window.btoa(binary);
         return base64.replace(/=/g, "").replace(/\+/g, "-").replace(/\//g, "_");
     },
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
encode: function (buffer) {
const base64 = window.btoa(String.fromCharCode(...new Uint8Array(buffer)));
return base64.replace(/=/g, "").replace(/\+/g, "-").replace(/\//g, "_");
encode: function (buffer) {
const bytes = new Uint8Array(buffer);
let binary = "";
const chunkSize = 0x8000;
for (let i = 0; i < bytes.length; i += chunkSize) {
binary += String.fromCharCode(...bytes.subarray(i, i + chunkSize));
}
const base64 = window.btoa(binary);
return base64.replace(/=/g, "").replace(/\+/g, "-").replace(/\//g, "_");
},
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@src/main/resources/static/js/base64url.js` around lines 20 - 22, The encode
function uses String.fromCharCode(...new Uint8Array(buffer)) which can hit
argument count limits for large buffers; replace the spread usage with a chunked
conversion: create a Uint8Array bytes = new Uint8Array(buffer), iterate in
slices (e.g. step = 0x8000), build a string by concatenating
String.fromCharCode.apply(null, bytes.subarray(i, i+step)) or using
String.fromCharCode(...slice) per chunk, then call window.btoa on the assembled
string and keep the existing replace chain to produce base64url; update the
encode function (and the local base64 variable/window.btoa call) to use this
chunking approach.

Comment thread src/main/resources/templates/check.html
Comment thread src/main/resources/templates/fragments/admin-sidenav.html Outdated

<div th:replace="fragments/form-errors :: errors"></div>
<div th:replace="fragments/success-message :: success"></div>
<div th:replace="~{fragments/form-errors :: errors}"></div>

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🟡 Minor

🧩 Analysis chain

🏁 Script executed:

#!/bin/bash
# Description: Verify duplicate Thymeleaf fragment names referenced by login.html.
# Expectation: each referenced fragment name should be defined exactly once per template.

rg -n -C2 'th:fragment="errors"|th:replace="~\{fragments/form-errors :: errors\}"' src/main/resources/templates

Repository: ithsjava25/project-backend-team4you

Length of output: 1119


Consolidate the duplicate errors fragments into a single definition.

fragments/form-errors.html defines th:fragment="errors" twice (lines 1 and 9), which makes the fragment resolution at login.html:17 unpredictable. Merge these into one fragment that handles both ${param.error} and ${error}.

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@src/main/resources/templates/login.html` at line 17,
fragments/form-errors.html currently defines th:fragment="errors" twice which
causes unpredictable resolution in login.html; edit fragments/form-errors.html
to remove the duplicate and consolidate into a single th:fragment="errors" that
renders the same markup for both cases by checking both ${param.error} and
${error} (e.g., use a combined conditional that prefers ${param.error} but falls
back to ${error} and displays the message), leaving login.html's
th:replace="~{fragments/form-errors :: errors}" unchanged so it resolves
deterministically.

Comment thread src/main/resources/templates/profile.html Outdated
@gvaguirres

Copy link
Copy Markdown
Contributor Author

@CodeRabbit check

@coderabbitai

coderabbitai Bot commented Apr 18, 2026

Copy link
Copy Markdown
Contributor

@gvaguirres Sure! I'll kick off a review of this PR right away.

✅ Actions performed

Review triggered.

Note: CodeRabbit is an incremental review system and does not re-review already reviewed commits. This command is applicable only when automatic reviews are paused.

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 1

🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Inline comments:
In `@src/main/java/backendlab/team4you/controller/SignupController.java`:
- Around line 37-39: The dashboard routes referenced by the template are
missing; add controller mappings in SignupController (or a new
DashboardController) for `@GetMapping`("/dashboard") and
`@GetMapping`("/dashboard/home") that return the dashboard view names (or redirect
to an existing template), so the template's @{/dashboard} and
hx-get="/dashboard/home" resolve; alternatively, update the template navigation
to point to existing endpoints if you prefer not to restore these routes—locate
SignupController and either restore/create methods named e.g. dashboard() and
dashboardHome() to fix the broken links.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro

Run ID: 60c2c27a-9541-4250-a1e3-7003edda36bc

📥 Commits

Reviewing files that changed from the base of the PR and between 5a723c3 and 6dcd489.

📒 Files selected for processing (5)
  • src/main/java/backendlab/team4you/config/CustomAuthenticationSuccessHandler.java
  • src/main/java/backendlab/team4you/config/SecurityConfig.java
  • src/main/java/backendlab/team4you/controller/SignupController.java
  • src/main/resources/templates/fragments/admin-sidenav.html
  • src/main/resources/templates/profile.html
✅ Files skipped from review due to trivial changes (2)
  • src/main/resources/templates/fragments/admin-sidenav.html
  • src/main/resources/templates/profile.html
🚧 Files skipped from review as they are similar to previous changes (2)
  • src/main/java/backendlab/team4you/config/CustomAuthenticationSuccessHandler.java
  • src/main/java/backendlab/team4you/config/SecurityConfig.java

Comment on lines +37 to +39
@GetMapping("/login/webauthn")
public String webauthnCheck() {
return "check";

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🔴 Critical

🧩 Analysis chain

🏁 Script executed:

#!/bin/bash
# Description: Verify dashboard links still have controller mappings.

echo "Controller mappings for /dashboard:"
rg -n -C3 '@(GetMapping|PostMapping|RequestMapping)\s*\([^)]*["'\'']/dashboard\b' src/main/java

echo
echo "Template/static references to /dashboard:"
rg -n -C2 '(/dashboard\b|@\{/dashboard\})' src/main/resources

Repository: ithsjava25/project-backend-team4you

Length of output: 1215


🏁 Script executed:

#!/bin/bash
# Search for any dashboard-related mappings that might exist
echo "Searching for all `@GetMapping/`@PostMapping/@RequestMapping containing 'dashboard':"
rg -i 'dashboard' src/main/java --type java -B2 -A2

echo
echo "Searching for any /dashboard* patterns in Java files:"
rg '"/dashboard' src/main/java --type java

Repository: ithsjava25/project-backend-team4you

Length of output: 216


Add a /dashboard controller endpoint or update the template navigation.

The /login/webauthn mapping is correctly aligned with SecurityConfig, but the removal of the /dashboard endpoint creates a broken navigation link. The template at src/main/resources/templates/dashboard-layout.html:27 references @{/dashboard} and uses hx-get="/dashboard/home", but no controller currently maps either route. Users navigating via the sidebar will encounter a 404 error.

Either restore the /dashboard controller mapping or update the template to point to a valid endpoint.

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@src/main/java/backendlab/team4you/controller/SignupController.java` around
lines 37 - 39, The dashboard routes referenced by the template are missing; add
controller mappings in SignupController (or a new DashboardController) for
`@GetMapping`("/dashboard") and `@GetMapping`("/dashboard/home") that return the
dashboard view names (or redirect to an existing template), so the template's
@{/dashboard} and hx-get="/dashboard/home" resolve; alternatively, update the
template navigation to point to existing endpoints if you prefer not to restore
these routes—locate SignupController and either restore/create methods named
e.g. dashboard() and dashboardHome() to fix the broken links.

This was linked to issues Apr 20, 2026
@gvaguirres gvaguirres removed a link to an issue Apr 20, 2026
@JohanHiths
JohanHiths merged commit 6692c92 into main Apr 21, 2026
2 checks passed
@MartinStenhagen
MartinStenhagen deleted the passkeys branch April 22, 2026 12:36
@coderabbitai coderabbitai Bot mentioned this pull request Apr 27, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Spring security user acess (s3-support) and passkeys

2 participants